//
//  IndexConfig.cpp
//  Chart
//
//  Created by CaoJun on 13-6-9.
//
//

#include "IndexConfig.h"
#include "YTXChartTools.h"
#include "UserInfo.h"

using namespace ytx;
using namespace std;


IndexConfig::IndexConfig(IndexType::IndexType indexType, string indexName, IndexChartType::IndexChartType indexChartType, const vector<string> type, const vector<string> name, const vector<double> value, const vector<pair<double, double> > range, bool enabled, const vector<double> ratio) : indexType(indexType), indexName(indexName), indexChartType(indexChartType), type(type), name(name), value(value),  range(range), enabled(enabled), ratio(ratio), indexChartViewType(0), particular(false) {
    indexPermission = 0;
}

IndexConfig::IndexConfig(IndexType::IndexType indexType, string indexName, IndexChartType::IndexChartType indexChartType, unsigned int indexChartViewType, const vector<string> type, const vector<string> name, const vector<double> value, const vector<pair<double, double> > range, bool enabled, const vector<double> ratio) : indexType(indexType), indexName(indexName), indexChartType(indexChartType), type(type), name(name), value(value),  range(range), enabled(enabled), ratio(ratio),  indexChartViewType(indexChartViewType), particular(false){
    indexPermission = 0;
}

IndexConfig::IndexConfig(IndexType::IndexType indexType) : indexType(indexType), indexChartViewType(0), particular(false) {
    indexPermission = 0;
}

vector<string> IndexConfig::arrayToVector(string input[], int length)
{
    vector<string> result;
    for (int i = 0; i< length; i++) {
        result.push_back(input[i]);
    }
    return result;
}

vector<double> IndexConfig::intToVector(double input[], int length)
{
    vector<double> result;
    for (int i = 0; i< length; i++) {
        result.push_back(input[i]);
    }
    return result;
}

//在这里增加 才能在附图点击时切换到该指标
//const map<IndexType::IndexType, IndexType::IndexType> IndexConfig::createKLineMainIndexReflect() {
//    map<IndexType::IndexType, IndexType::IndexType> result;
//    result.insert(make_pair(IndexType::TJ,IndexType::MA));
//    result.insert(make_pair(IndexType::MA,IndexType::BOLLIN));
//    result.insert(make_pair(IndexType::BOLLIN,IndexType::TJ));
//    return result;
//}
//
//const map<IndexType::IndexType, IndexType::IndexType> IndexConfig::mainKLineIndexReflect = IndexConfig::createKLineMainIndexReflect();
//
//const IndexType::IndexType IndexConfig::toggleKLineMainIndexType(IndexType::IndexType indexType){
//    return (*IndexConfig::mainKLineIndexReflect.find(indexType)).second;
//}


//在这里增加 才能在附图点击时切换到该指标 好像废弃了
//const map<IndexType::IndexType, IndexType::IndexType> IndexConfig::createKLineMinorIndexReflect() {
//    map<IndexType::IndexType, IndexType::IndexType> result;
//    result.insert(make_pair(IndexType::VOLUME,IndexType::MACD));
//    result.insert(make_pair(IndexType::MACD,IndexType::KDJ));
//    result.insert(make_pair(IndexType::KDJ,IndexType::RSI));
//    result.insert(make_pair(IndexType::RSI,IndexType::BIAS));
//    result.insert(make_pair(IndexType::BIAS,IndexType::VOLUME));
//    return result;
//}
//
//const map<IndexType::IndexType, IndexType::IndexType> IndexConfig::minorKLineIndexReflect = IndexConfig::createKLineMinorIndexReflect();

//const IndexType::IndexType IndexConfig::toggleKLineMinorIndexType(IndexType::IndexType indexType){
//    return (*IndexConfig::minorKLineIndexReflect.find(indexType)).second;
//}
//ADDIndex:
const IndexType::IndexType IndexConfig::getIndexTypeByString(string type) {

    if( type == "MA"){
        return IndexType::MA;
    }
    else if( type == "EconomicCalendar"){
        return IndexType::EconomicCalendar;
    }
    else if( type == "VOLUME"){
        return IndexType::VOLUME;
    }
    else if( type == "Tuov"){
        return IndexType::Tuov;
    }
    else if( type == "BOLLIN"){
        return IndexType::BOLLIN;
    }
    else if( type == "TJ"){
        return IndexType::TJ;
    }
    else if( type == "MACD"){
        return IndexType::MACD;
    }
    else if( type == "KDJ"){
        return IndexType::KDJ;
    }
    else if( type == "RSI"){
        return IndexType::RSI;
    }
    else if( type == "BIAS"){
        return IndexType::BIAS;
    }
    else if( type == "CCI"){
        return IndexType::CCI;
    }
    else if (type == "GameMatrix") {
        return IndexType::GameMatrix;
    }
    else if (type == "HJJT") {
        return IndexType::HJJT;
    }
    return IndexType::EMPTY;
}

const IndexChartType::IndexChartType IndexConfig::getIndexChartTypeByString(string type) {
    if( type == "main"){
        return IndexChartType::main;
    }
    return IndexChartType::minor;
}

const YTXJson::Value IndexConfig::toJSONValue() const
{
    YTXJson::Value json;

    json["indexType"] = (int)indexType;
    json["indexChartType"] = (int)indexChartType;
    json["indexName"] = indexName;

    YTXJson::Value typeArray;
    for (vector<string>::const_iterator it = type.begin() ; it!=type.end(); ++it) {
        typeArray.append((*it));
    }
    json["type"] = typeArray;

    YTXJson::Value nameArray;
    for (vector<string>::const_iterator it = name.begin() ; it!=name.end(); ++it) {
        nameArray.append((*it));
    }
    json["name"] = nameArray;

    YTXJson::Value valueArray;
    for (vector<double>::const_iterator it = value.begin() ; it!=value.end(); ++it) {
        valueArray.append((*it));
    }
    json["value"] = valueArray;

    YTXJson::Value ratioArray;
    for (vector<double>::const_iterator it = ratio.begin() ; it!=ratio.end(); ++it) {
        ratioArray.append((*it));
    }
    json["ratio"] = ratioArray;

    YTXJson::Value rangeArray;
    for (vector<pair<double, double> >::const_iterator it = range.begin() ; it!=range.end(); ++it) {
        YTXJson::Value rangeTemp;
        rangeTemp["first"] = (*it).first;
        rangeTemp["second"] = (*it).second;
        rangeArray.append(rangeTemp);
    }
    json["range"] = rangeArray;

    json["enabled"] = enabled;

    json["indexChartViewType"] = indexChartViewType;

    return json;
}

const string IndexConfig::toJSONString() const
{
    YTXJson::FastWriter fastWriter;
    return fastWriter.write(toJSONValue());
}

IndexConfig IndexConfig::createByJSONString(string json)
{
    YTXJson::Value parsedFromString;
    YTXJson::Reader reader;
    bool parsingSuccessful = reader.parse(json, parsedFromString);

    return parsingSuccessful ? IndexConfig::create(parsedFromString) : IndexConfig();
}


IndexConfig IndexConfig::create(YTXJson::Value json)
{
    if (!json.isMember("indexType")) {
        return IndexConfig();
    }
    IndexType::IndexType indexType = static_cast<IndexType::IndexType>(json["indexType"].asInt());

    IndexChartType::IndexChartType indexChartType = static_cast<IndexChartType::IndexChartType>(json["indexChartType"].asInt());

    string indexName = json["indexName"].asString();

    YTXJson::Value typeArray = json["type"];
    vector<string> type;
    for (YTXJson::Value::iterator it = typeArray.begin(); it != typeArray.end(); ++it) {
        type.push_back((*it).asString());
    }

    YTXJson::Value nameArray = json["name"];
    vector<string> name;
    for (YTXJson::Value::iterator it = nameArray.begin(); it != nameArray.end(); ++it) {
        name.push_back((*it).asString());
    }

    YTXJson::Value valueArray = json["value"];
    vector<double> value;
    for (YTXJson::Value::iterator it = valueArray.begin(); it != valueArray.end(); ++it) {
        value.push_back((*it).asDouble());
    }

    YTXJson::Value ratioArray = json["ratio"];
    vector<double> ratio;
    for (YTXJson::Value::iterator it = ratioArray.begin(); it != ratioArray.end(); ++it) {
        ratio.push_back((*it).asDouble());
    }

    YTXJson::Value rangeArray = json["range"];
    vector<pair<double, double> > range;
    for (YTXJson::Value::iterator it = rangeArray.begin(); it != rangeArray.end(); ++it) {
        YTXJson::Value rangeTemp = (*it);
        range.push_back( make_pair(rangeTemp["first"].asDouble(), rangeTemp["second"].asDouble() ) );
    }

    bool enabled = json["enabled"].asBool();

    unsigned int indexChartViewType = 0;

    if (json.isMember("indexChartViewType")) {
        indexChartViewType = json["indexChartViewType"].asUInt();
    }

    return IndexConfig(indexType, indexName, indexChartType, indexChartViewType, type, name, value, range, enabled);
}


const map<IndexType::IndexType, IndexConfig>__attribute__((annotate("oclint:suppress[long method]"))) IndexConfig::initIndex(){
    map<IndexType::IndexType, IndexConfig> result;
    vector<pair<double, double> > range1_250 (3, make_pair(1, 250));

    string ma_type[6] = {"#11F0C3", "MA1", "#FF4C94", "MA2", "#FFB400", "MA3"};
    string ma_name[3] = {"移动平均线1", "移动平均线2", "移动平均线3"};
    double ma_value[3] = { 5, 10, 20};

    string bollin_type[6] = {"#11F0C3", "UP", "#FF4C94", "MID", "#FFB400", "DOWN"};
    string bollin_name[3] = {"标准差", "宽度", "DOWN"};
    double bollin_value[2] = { 26, 2 };
    vector<pair<double, double> > BOLLIN_range;
    BOLLIN_range.push_back(pair<double, double>(2, 120));
    BOLLIN_range.push_back(pair<double, double>(1, 100));

    string tj_type[10] = {"#69d94a", "乾2", "#5f955b", "乾1", "#414242", "太极线", "#a8403a", "坤1", "#eb5d5c", "坤2"};
    string tj_name[5] = {"乾2", "乾1", "太极线", "坤1", "坤2"};
    double tj_value[1] = { 4 };
    vector<pair<double, double> > TJ_range;
    TJ_range.push_back(pair<double, double>(2, 99));
    vector<double > TJ_ratio;
    TJ_ratio.push_back(0.0618);
    TJ_ratio.push_back(0.0382);
    TJ_ratio.push_back(8.27);
    TJ_ratio.push_back(10.27);

    string macd_type[6] = {"#11F0C3", "DEA", "#FF4C94", "DIF", "#FFB400", "MACD"};
    string macd_name[3] = {"快速平滑移动", "移动平均", "慢速平滑移动"};
    double macd_value[3] = { 12, 9, 26};
    vector<pair<double, double> > MACD_range;
    MACD_range.push_back(pair<double, double>(2, 60));
    MACD_range.push_back(pair<double, double>(2, 90));
    MACD_range.push_back(pair<double, double>(2, 60));

    string kdj_type[6] = {"#11F0C3", "K", "#FF4C94", "D", "#FFB400", "J"};
    string kdj_name[3] = {"天数1", "天数2", "天数3"};
    double kdj_value[3] = { 9, 3, 3};
    vector<pair<double, double> > KDJ_range;
    KDJ_range.push_back(pair<double, double>(2, 60));
    KDJ_range.push_back(pair<double, double>(2, 90));
    KDJ_range.push_back(pair<double, double>(2, 60));

    string volume_type[6] = {"#01C8F2", "成交量", "#FF4C94", "MA5", "#FFB400", "MA10"};
    string volume_name[3] = {"VOL", "MA5", "MA10"};
    double volume_value[2] = {5, 10};
    vector<pair<double, double> > volume_range (3, make_pair(1, 250));
    
    string tuov_type[6] = {"#01C8F2", "成交额", "#FF4C94", "MA5", "#FFB400", "MA10"};
    string tuov_name[3] = {"成交额", "5日均线", "10日均线"};
    double tuov_value[2] = {5, 10};//同花顺上的成交量、成交额没对应的日期
    vector<pair<double, double> > tuov_range(1, pair<double, double>(0, 60));// 用处不明？
    
    string RSI_type[4] = {"#11F0C3", "RSI1", "#FF4C94", "RSI2"};
    string RSI_name[2] = {"相对强弱1", "相对强弱2"};
    double RSI_value[2] = {12, 6};
    vector<pair<double, double> > RSI_range;
    RSI_range.push_back(pair<double, double>(2, 60));
    RSI_range.push_back(pair<double, double>(2, 30));

    string BIAS_type[2] = {"#11F0C3", "BIAS"};
    string BIAS_name[1] = {"移动平均"};
    double BIAS_value[1] = {6};
    vector<pair<double, double> > BIAS_range(1, pair<double, double>(2, 30));

    //增加指标 注意下标 尤其是range
    //依赖顺序
    IndexConfig tj = IndexConfig(IndexType::TJ, "太极", IndexChartType::main, IndexChartViewTypeKLine, IndexConfig::arrayToVector(tj_type, 10) , IndexConfig::arrayToVector(tj_name, 5), IndexConfig::intToVector(tj_value, 1), TJ_range, false, TJ_ratio);

    tj.particular = true;
    tj.indexPermission = 0;
    
    vector<string> QK_type;
    vector<string> QK_name;
    vector<double> QK_value;
    vector<pair<double, double> > QK_range;

    IndexConfig qk = IndexConfig(IndexType::QK, "乾坤线", IndexChartType::main, IndexChartViewTypeKLine, QK_type , QK_name, QK_value, QK_range, false);

    qk.particular = true;
    qk.indexPermission = 0;
    
    vector<string> QKT_type;
    vector<string> QKT_name;
    vector<double> QKT_value;
    vector<pair<double, double> > QKT_range;
    
    IndexConfig qkt = IndexConfig(IndexType::QKT, "乾坤图", IndexChartType::main, IndexChartViewTypeKLine, QKT_type , QKT_name, QKT_value, QKT_range, false);
    
    qkt.particular = true;
    qkt.indexPermission = 0;
    
    vector<string> gm_type;
    vector<string> gm_name;
    vector<double> gm_value;
    vector<pair<double, double> > gm_range;
    
    IndexConfig gm = IndexConfig(IndexType::GameMatrix, "博弈", IndexChartType::main, IndexChartViewTypeKLine, QKT_type , QKT_name, QKT_value, QKT_range, false);
    
    gm.particular = true;
    gm.indexPermission = 0;
    
    vector<string> gs_type;
    vector<string> gs_name;
    vector<double> gs_value;
    vector<pair<double, double> > gs_range;
    
    IndexConfig gs = IndexConfig(IndexType::HJJT, "HJJT", IndexChartType::main, IndexChartViewTypeKLine, QKT_type , QKT_name, QKT_value, QKT_range, false);
    
    gs.particular = true;
    gs.indexPermission = 0;
    
    IndexConfig gLsp = IndexConfig(IndexType::LSP, "LSP", IndexChartType::main, IndexChartViewTypeKLine, QKT_type , QKT_name, QKT_value, QKT_range, false);
    gLsp.particular = true;
    gLsp.indexPermission = 0;

    result.insert(make_pair(IndexType::TJ, tj));

    result.insert(make_pair(IndexType::QK, qk));
    
    result.insert(make_pair(IndexType::QKT, qkt));
    
    result.insert(make_pair(IndexType::GameMatrix, gm));
    
    result.insert(make_pair(IndexType::HJJT, gs));
    
    result.insert(make_pair(IndexType::LSP, gLsp));

    result.insert(make_pair(IndexType::MA, IndexConfig(IndexType::MA, "MA", IndexChartType::main, IndexChartViewTypeKLine, IndexConfig::arrayToVector(ma_type, 6) , IndexConfig::arrayToVector(ma_name, 3), IndexConfig::intToVector(ma_value, 3), range1_250)));

    result.insert(make_pair(IndexType::BOLLIN, IndexConfig(IndexType::BOLLIN, "BOLL", IndexChartType::main, IndexChartViewTypeKLine, IndexConfig::arrayToVector(bollin_type, 6) , IndexConfig::arrayToVector(bollin_name, 3), IndexConfig::intToVector(bollin_value, 2), BOLLIN_range)));

    //附图指标

//    result.insert(make_pair(IndexType::EconomicCalendar, IndexConfig(IndexType::EconomicCalendar, "财经日历", IndexChartType::minor, IndexChartViewTypeAVG,vector<string>(), vector<string>(), vector<double>() , vector<pair<double, double> >(), false )));

    result.insert(make_pair(IndexType::VOLUME, IndexConfig(IndexType::VOLUME, "成交量", IndexChartType::minor, IndexChartViewTypeKLine | IndexChartViewTypeAVG, IndexConfig::arrayToVector(volume_type, 6), IndexConfig::arrayToVector(volume_name, 3),IndexConfig::intToVector(volume_value, 2) , volume_range, false )));
    
    result.insert(make_pair(IndexType::Tuov, IndexConfig(IndexType::Tuov, "成交额", IndexChartType::minor, IndexChartViewTypeKLine, IndexConfig::arrayToVector(tuov_type, 6), IndexConfig::arrayToVector(tuov_name, 3),IndexConfig::intToVector(tuov_value, 2) , tuov_range, false )));
    
    result.insert(make_pair(IndexType::MACD, IndexConfig(IndexType::MACD, "MACD", IndexChartType::minor, IndexChartViewTypeKLine,IndexConfig::arrayToVector(macd_type, 6),IndexConfig::arrayToVector(macd_name, 3),IndexConfig::intToVector(macd_value, 3) , MACD_range)));

    result.insert(make_pair(IndexType::KDJ, IndexConfig(IndexType::KDJ, "KDJ", IndexChartType::minor, IndexChartViewTypeKLine,IndexConfig::arrayToVector(kdj_type, 6),IndexConfig::arrayToVector(kdj_name, 3),IndexConfig::intToVector(kdj_value, 3) , KDJ_range)));

    result.insert(make_pair(IndexType::RSI, IndexConfig(IndexType::RSI, "RSI", IndexChartType::minor, IndexChartViewTypeKLine, IndexConfig::arrayToVector(RSI_type, 4), IndexConfig::arrayToVector(RSI_name, 2),IndexConfig::intToVector(RSI_value, 2) , RSI_range )));

    result.insert(make_pair(IndexType::BIAS, IndexConfig(IndexType::BIAS, "BIAS", IndexChartType::minor, IndexChartViewTypeKLine, IndexConfig::arrayToVector(BIAS_type, 2), IndexConfig::arrayToVector(BIAS_name, 1),IndexConfig::intToVector(BIAS_value, 1) , BIAS_range )));

    //ADDIndex:
    vector<pair<double, double> > CCI_range(1, pair<double, double>(3, 99));
//    string CCI_type[2] = {"#11F0C3", "CCI"};
//    string CCI_name[1] = {"CCI"};
//    double CCI_value[1] = {14};
//    vector<pair<double, double> > CCI_range(1, pair<double, double>(3, 99));
//    result.insert(make_pair(IndexType::CCI, IndexConfig(IndexType::CCI, "CCI", IndexChartType::minor, IndexChartViewTypeKLine, IndexConfig::arrayToVector(CCI_type, 2), IndexConfig::arrayToVector(CCI_name, 1),IndexConfig::intToVector(CCI_value, 1) , CCI_range )));

    return result;
}

bool IndexConfig::eqauls(const ytx::IndexConfig &indexConfig){
    return indexType == indexConfig.indexType &&
    indexChartType == indexConfig.indexChartType &&
    enabled == indexConfig.enabled &&
    std::equal(type.begin(), type.end(), indexConfig.type.begin()) &&
    std::equal(name.begin(), name.end(), indexConfig.name.begin()) &&
    std::equal(value.begin(), value.end(), indexConfig.value.begin()) &&
    std::equal(range.begin(), range.end(), indexConfig.range.begin()) &&
    indexChartViewType == indexConfig.indexChartViewType;
}

IndexConfig IndexConfig::extend(const IndexConfig & indexConfig){
    if (indexType != indexConfig.indexType ||
        indexChartType != indexConfig.indexChartType) {
        return *this;
    }

    IndexConfig result = IndexConfig(indexType, indexName, indexChartType, type, name, value, range, enabled, ratio);

    result.particular = particular;

    result.indexName = indexConfig.indexName;

    if (indexConfig.type.size() > 0) {
        result.type = indexConfig.type;
    }

    if (indexConfig.name.size() > 0) {
        result.name = indexConfig.name;
    }

    if (indexConfig.value.size() > 0) {
        result.value = indexConfig.value;
    }

    if (indexConfig.range.size() > 0) {
        result.range = indexConfig.range;
    }

    result.enabled = indexConfig.enabled;

    if (indexConfig.ratio.size() > 0) {
        result.ratio = indexConfig.ratio;
    }

    if (indexConfig.particular) {
        result.particular = particular;
        result.setIndexPermission(indexConfig.indexPermission);
    }

    if (indexConfig.indexChartViewType != 0) {
        result.indexChartViewType = indexConfig.indexChartViewType;
    }

    return result;
}

void IndexConfig::extendSelf(const IndexConfig & indexConfig)
{
    if (indexType != indexConfig.indexType ||
        indexChartType != indexConfig.indexChartType) {
        return;
    }
    indexName = indexConfig.indexName;
    if (indexConfig.type.size() > 0) {
        
        type = indexConfig.type;
    }

    if (indexConfig.name.size() > 0) {
        name = indexConfig.name;
    }

    if (indexConfig.value.size() > 0) {
        value = indexConfig.value;
    }

    if (indexConfig.range.size() > 0) {
        range = indexConfig.range;
    }

    enabled = indexConfig.enabled;

    if (indexConfig.ratio.size() > 0) {
        ratio = indexConfig.ratio;
    }

    if (indexConfig.particular) {
//        result.particular = particular;
        setIndexPermission(indexConfig.indexPermission);
    }

    if (indexConfig.indexChartViewType != 0) {
        indexChartViewType = indexConfig.indexChartViewType;
    }

}

void IndexConfig::clearIndexPermission()
{
    this->indexPermission = -1;
}

void IndexConfig::setIndexPermission(int indexPermission)
{
    this->particular = true;
    this->indexPermission = indexPermission;
}

bool IndexConfig::isParticularAndHas()
{
    return this->particular;
}

bool IndexConfig::hasIndex()
{
    if (this->particular) {
        return this->indexPermission > 0;
    }
    return true;
}

int IndexConfig::getIndexPermission()
{
    if (!this->hasIndex()) {
        return 0;
    }

    return this->indexPermission;
}

const pair<string, string> IndexConfig::getParticularIndexImagePath(IndexType::IndexType indexType)
{
    pair<string, string> ret;

    switch (indexType) {
        case IndexType::QK:{
            UserInfo * userInfo = UserInfo::getInstance();
            if (userInfo->getServerId() == TT) {
                ret = make_pair("yik_btn_selected.png", "yik_btn_default.png");
            }
            else {
                ret = make_pair("qiankun_btn_selected.png", "qiankun_btn_default.png");
            }
            break;
        }
        case IndexType::QKT:{
            ret = make_pair("qiankun_btn_selected.png", "qiankun_btn_default.png");
            break;
        }
        case IndexType::GameMatrix:{
            //TODO 图片
            ret = make_pair("gamevatrix_btn_selected.png", "gamevatrix_btn_default.png");
            break;
        }
        case IndexType::HJJT:{
            //TODO("黄金阶梯图标");
            ret = make_pair("gamevatrix_btn_selected.png", "gamevatrix_btn_default.png");
            break;
        }
        case IndexType::TJ:
        default:
            ret = make_pair("taiji_btn_selected.png", "taiji_btn_default.png");
            break;
    }
    return ret;

}

const string IndexConfig::getIndexName()
{
    if (indexType == IndexType::QK) {
        UserInfo * userInfo = UserInfo::getInstance();
        if (userInfo->getServerId() == TT) {
            return "易K";
        }
    }

    return indexName;
}
